package kr.co.iniline.rmkb.core;

import kr.co.iniline.rumkb.server.RmkbUtil;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.Mesh;
import com.badlogic.gdx.graphics.VertexAttribute;
import com.badlogic.gdx.graphics.Texture.TextureFilter;
import com.badlogic.gdx.graphics.VertexAttributes.Usage;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.BitmapFont.Glyph;
import com.badlogic.gdx.graphics.glutils.ShaderProgram;


class Kub {
	static final byte RED = 0;
	static final byte BLUE = 1;
	static final byte YELLOW = 2;
	static final byte BLACK = 3;
	
	static float CUBE_WIDTH = 0.2f;
	static float CUBE_HEIGHT = 0.3f;

	static float CUBE_TEXT_SCALE = 0.4f;
	static float CUBE_TEXT_WIDTH = CUBE_WIDTH*CUBE_TEXT_SCALE;
	static float CUBE_TEXT_HEIGHT = CUBE_HEIGHT*CUBE_TEXT_SCALE;
	
	static Mesh cubeMesh = null;
	static Kub CUBE_TABLES[] = new Kub[13*4+1];
	
	Mesh cubeInMesh = null;
	Mesh cubeInMesh2 = null;
	
	/** (Red, Blue, Yellow, Black)*n13 + Joker */
	
	
	int col = -1;
	int num = -1;
	
	
	public Kub(byte col, int num) {
		Color textRendColor = null;
		if( col == RED ) {
			textRendColor = Color.RED;
		} else if( col == BLUE ) {
			textRendColor = Color.BLUE;
		} else if( col == YELLOW ) {
			textRendColor = Color.YELLOW;
		} else if( col == BLACK ) {
			textRendColor = Color.BLACK;
		} else {
			textRendColor = Color.WHITE;
		}
		this.num = num;
		
		BitmapFont font = Resource.getFont("default");
		if( isJoker() ) {
			cubeInMesh = new Mesh(true, 4, 4, new VertexAttribute(Usage.Position, 3, "a_position"), new VertexAttribute(Usage.TextureCoordinates, 2, "a_texCoords1")  );
			float uv[] = Resource.getUV("joker");
			cubeInMesh.setVertices(new float[]{
					0f, 0f, 0f, uv[0], uv[1],
					0f, -CUBE_TEXT_HEIGHT, 0f, uv[2], uv[3],
					CUBE_TEXT_WIDTH, -CUBE_TEXT_HEIGHT, 0f, uv[4], uv[5],
					CUBE_TEXT_WIDTH, 0f, 0f, uv[6], uv[7]
			});
			cubeInMesh.setIndices(new short[]{0,1,2,3});
		} else {
			Glyph glyph = font.getData().getGlyph( String.valueOf(num).charAt(0) );
			cubeInMesh = new Mesh(true, 4, 4, new VertexAttribute(Usage.Position, 3, "a_position"), new VertexAttribute(Usage.ColorPacked, 4, ShaderProgram.COLOR_ATTRIBUTE), new VertexAttribute(Usage.TextureCoordinates, 2, "a_texCoords1")  );
			cubeInMesh.setVertices(new float[]{
					0f, 0f, 0f, textRendColor.toFloatBits(), glyph.u, glyph.v2,
					0f, -CUBE_TEXT_HEIGHT, 0f, textRendColor.toFloatBits(), glyph.u, glyph.v,
					CUBE_TEXT_WIDTH, -CUBE_TEXT_HEIGHT, 0f, textRendColor.toFloatBits(), glyph.u2, glyph.v,
					CUBE_TEXT_WIDTH, 0f, 0f, textRendColor.toFloatBits(), glyph.u2, glyph.v2
			});
			cubeInMesh.setIndices(new short[]{0,1,2,3});
			if( num >= 10 ) {
				glyph = font.getData().getGlyph( String.valueOf(num).charAt(1) );
				cubeInMesh2 = new Mesh(true, 4, 4, new VertexAttribute(Usage.Position, 3, "a_position"), new VertexAttribute(Usage.ColorPacked, 4, ShaderProgram.COLOR_ATTRIBUTE), new VertexAttribute(Usage.TextureCoordinates, 2, "a_texCoords1")  );
				cubeInMesh2.setVertices(new float[]{
						0f, 0f, 0f, textRendColor.toFloatBits(), glyph.u, glyph.v2,
						0f, -CUBE_TEXT_HEIGHT, 0f, textRendColor.toFloatBits(), glyph.u, glyph.v,
						CUBE_TEXT_WIDTH, -CUBE_TEXT_HEIGHT, 0f, textRendColor.toFloatBits(), glyph.u2, glyph.v,
						CUBE_TEXT_WIDTH, 0f, 0f, textRendColor.toFloatBits(), glyph.u2, glyph.v2
				});
				cubeInMesh2.setIndices(new short[]{0,1,2,3});
			}
		}
	}
	
	static void loadKubs() {
		
		float cubeUV[] = Resource.getUV("cubeface");
		cubeMesh = new Mesh(true, 4, 4, new VertexAttribute(Usage.Position, 3, "a_position"), new VertexAttribute(Usage.TextureCoordinates, 2, "a_texCoords1") );
		cubeMesh.setVertices(new float[]{
			0f, 0f, 0f, cubeUV[0], cubeUV[1],
			0f, -CUBE_HEIGHT, 0f, cubeUV[2], cubeUV[3],
			CUBE_WIDTH, -CUBE_HEIGHT, 0f, cubeUV[4], cubeUV[5],
			CUBE_WIDTH, 0f, 0f, cubeUV[6], cubeUV[7]
		});
		cubeMesh.setIndices(new short[]{0,1,2,3});
		
		/** Red->Blue->Yellow->Black */
		for(byte col=RED; col<=BLACK; col++) {
			for(int i=0;i<13;i++) {
				CUBE_TABLES[col*13 + i] = new Kub(col, i+1);
			}
		}
		int colorCount = 4;
		CUBE_TABLES[colorCount*13] = new Kub(BLACK, -1);
	}
	
	static void disposeKubs() {
		
	}
	
	static Kub getCube(byte col, int num) {
		if( num == 0 ) {
			return CUBE_TABLES[ CUBE_TABLES.length-1 ];
		}
		return CUBE_TABLES[col*13+(num-1)];
	}
	
	static Kub getCube(int data) {
		if( data == 0 ) {
			return CUBE_TABLES[ CUBE_TABLES.length-1 ];
		}
		return getCube( RmkbUtil.getColor( data ), RmkbUtil.getKubNum( data ) );
	}
	
	public boolean isJoker() {
		if(num == -1) return true;
		return false;
	}
	
	public void render() {
		Gdx.gl10.glPushMatrix();
		Resource.bindTexture("cubeface");
		cubeMesh.render(GL10.GL_TRIANGLE_FAN);
		
		if( isJoker() ) {
			Resource.bindTexture("joker");
		} else {
			/** inner bind */
			BitmapFont font = Resource.getFont("default");
			font.getRegion().getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear);
			Gdx.gl10.glEnable(GL10.GL_BLEND);
			Gdx.gl10.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
		}
		
		if( isJoker() ) {
			Gdx.gl10.glTranslatef( (CUBE_WIDTH-CUBE_TEXT_WIDTH)/2f, -(CUBE_HEIGHT-CUBE_TEXT_HEIGHT)/2f, 0.01f);
			Gdx.gl10.glEnable(GL10.GL_BLEND);
			Gdx.gl10.glBlendFunc(GL10.GL_ONE_MINUS_SRC_COLOR, GL10.GL_SRC_COLOR);
			cubeInMesh.render(GL10.GL_TRIANGLE_FAN);
		} else if( num >= 10 ) {
			Gdx.gl10.glTranslatef( (CUBE_WIDTH-CUBE_TEXT_WIDTH*2)/2f, -(CUBE_HEIGHT-CUBE_TEXT_HEIGHT)/2f, 0.01f);
			cubeInMesh.render(GL10.GL_TRIANGLE_FAN);
			Gdx.gl10.glTranslatef( CUBE_TEXT_WIDTH, 0f, 0f);
			cubeInMesh2.render(GL10.GL_TRIANGLE_FAN);
		} else {
			Gdx.gl10.glTranslatef( (CUBE_WIDTH-CUBE_TEXT_WIDTH)/2f, -(CUBE_HEIGHT-CUBE_TEXT_HEIGHT)/2f, 0.01f);
			cubeInMesh.render(GL10.GL_TRIANGLE_FAN);
		}
		
		Gdx.gl10.glDisable(GL10.GL_BLEND);
		Gdx.gl10.glPopMatrix();
	}
	
	public int toKubData() {
		if( isJoker() ) {
			return 0;
		} else {
			return RmkbUtil.toKubData(col, num);
		}
	}
	
	public String toString() {
		return RmkbUtil.toKubString( toKubData() );
	}
}